package com.sychip.fhc.lib.base

import android.app.Activity
import android.content.Context
import android.view.animation.AnimationUtils
import androidx.annotation.StringRes
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.statusBars
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.ParagraphStyle
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.OffsetMapping
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.sp
import androidx.core.view.WindowCompat
import androidx.navigation.NavBackStackEntry
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import com.sychip.fhc.app.todo.R
import com.sychip.fhc.app.wsn.nav.NAV_JSON_ARG
import java.text.DecimalFormat
import kotlin.math.max
import kotlin.math.min
import androidx.compose.material.TopAppBar
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp

/**
 * 解析navigation时的参数
 * @receiver NavBackStackEntry
 * @return Pair<T?, String?>  Pair<解析后的对象，原始Json String参数>
 */
inline fun <reified T : Any> NavBackStackEntry.navArguments(): Pair<T?, String?> {
    val navJsonArg = arguments?.getString(NAV_JSON_ARG)
    val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
    val parsed = navJsonArg?.let { json ->
        moshi.adapter(T::class.java).lenient().fromJson(json)
    }
    return Pair(parsed, navJsonArg)
}


fun String.isInt(canEmpty: Boolean = false): Boolean {
    if(canEmpty){
        if(this.isEmpty()) return true
    }
    try {
        this.toInt()
        return true
    } catch (ex: NumberFormatException) {
        return false
    }
}

fun String.isDouble(canEmpty: Boolean = true): Boolean {
    if(canEmpty){
        if(this.isEmpty()) return true
    }
    try {
        this.toDouble()
        return true
    } catch (ex: NumberFormatException) {
        return false
    }
}

@Composable
fun MultipleStylesInText() {
    Text(
        buildAnnotatedString {
            withStyle(style = SpanStyle(color = Color.Blue)) {
                append("H")
            }
            append("ello ")

            withStyle(style = SpanStyle(fontWeight = FontWeight.Bold, color = Color.Red)) {
                append("W")
            }
            append("orld")
        }
    )
}

@Composable
fun BuildParagraphStyle() {
    Text(
        buildAnnotatedString {
            withStyle(style = ParagraphStyle(lineHeight = 30.sp)) {
                withStyle(style = SpanStyle(color = Color.Blue)) {
                    append("Hello\n")
                }
                withStyle(
                    style = SpanStyle(
                        fontWeight = FontWeight.Bold, color = Color.Red
                    )
                ) {
                    append("World\n")
                }
                append("Compose")
            }
        }
    )
}


class ThousandSeparatorVisualTransformation(
    var maxFractionDigits: Int = Int.MAX_VALUE,
    var minFractionDigits: Int = 0
) : VisualTransformation {
    private val symbols = DecimalFormat().decimalFormatSymbols
    private val commaReplacementPattern = Regex("\\B(?=(?:\\d{3})+(?!\\d))")

    override fun filter(text: AnnotatedString): TransformedText {
        if (text.isEmpty())
            return TransformedText(text, OffsetMapping.Identity)

        val comma = symbols.groupingSeparator
        val dot = symbols.decimalSeparator
        val zero = symbols.zeroDigit

        var (intPart, fracPart) = text.text.split(dot)
            .let { Pair(it[0], it.getOrNull(1)) }

        val normalizedIntPart =
            if (intPart.isEmpty() && fracPart != null) zero.toString() else intPart

        val integersWithComma =
            normalizedIntPart.replace(commaReplacementPattern, comma.toString())

        val minFractionDigits = min(this.maxFractionDigits, this.minFractionDigits)
        if (minFractionDigits > 0 || !fracPart.isNullOrEmpty()) {
            if (fracPart == null)
                fracPart = ""

            fracPart = fracPart.take(maxFractionDigits).padEnd(minFractionDigits, zero)
        }

        val newText = AnnotatedString(
            integersWithComma + if (fracPart == null) "" else ".$fracPart",
            text.spanStyles,
            text.paragraphStyles
        )

        val offsetMapping = ThousandSeparatorOffsetMapping(
            intPart.length,
            integersWithComma.length,
            newText.length,
            integersWithComma.indices.filter { integersWithComma[it] == comma }.asSequence(),
            normalizedIntPart != intPart
        )

        return TransformedText(newText, offsetMapping)
    }

    private inner class ThousandSeparatorOffsetMapping(
        val originalIntegerLength: Int,
        val transformedIntegersLength: Int,
        val transformedLength: Int,
        val commaIndices: Sequence<Int>,
        addedLeadingZero: Boolean
    ) : OffsetMapping {
        val commaCount = calcCommaCount(originalIntegerLength)
        val leadingZeroOffset = if (addedLeadingZero) 1 else 0

        override fun originalToTransformed(offset: Int): Int =
            if (offset >= originalIntegerLength)
                if (offset - originalIntegerLength > maxFractionDigits)
                    transformedLength
                else
                    offset + commaCount + leadingZeroOffset
            else
                offset + (commaCount - calcCommaCount(originalIntegerLength - offset))

        override fun transformedToOriginal(offset: Int): Int =
            if (offset >= transformedIntegersLength)
                min(offset - commaCount, transformedLength) - leadingZeroOffset
            else
                offset - commaIndices.takeWhile { it <= offset }.count()

        private fun calcCommaCount(intDigitCount: Int) =
            max((intDigitCount - 1) / 3, 0)
    }
}

@Composable
fun rememberKeyboardState(): State<Boolean> {
    val density = LocalDensity.current
    val windowInsets = WindowInsets.ime
    return remember(windowInsets, density) {
        derivedStateOf {
            windowInsets.getBottom(density) > 0
        }
    }
}


//@Composable
//fun StatusBarBox(offsetTop: Int = 46){
//    if(offsetTop > 0) {
//        Box(
//            modifier = Modifier.height(offsetTop.dp).fillMaxWidth().background(colorScheme.primary),
//        )
//    }
//}
//
//@Composable
//fun BottomBarBox(offsetBottom: Int = 16,color: Color = Color.White) {
//    if(offsetBottom > 0) {
//        Box(
//            modifier = Modifier.height(offsetBottom.dp).fillMaxWidth().background(color),
//        )
//    }
//}

fun Activity.setStatusBarTextColor(isDark: Boolean) {
    WindowCompat.getInsetsController(window, window.decorView).apply {
        isAppearanceLightStatusBars = isDark // 直接赋值更简洁
    }
}


fun slideInLeft(context: Context): EnterTransition {
    val anim = AnimationUtils.loadAnimation(context, R.anim.slide_in_left)
    return slideInHorizontally(
        initialOffsetX = { -it }, // 从左侧进入
        animationSpec = tween(durationMillis = anim.duration.toInt())
    ) + fadeIn(animationSpec = tween(anim.duration.toInt()))
}

fun slideOutLeft(context: Context): ExitTransition {
    val anim = AnimationUtils.loadAnimation(context, R.anim.slide_out_left)
    return slideOutHorizontally(
        targetOffsetX = { -it }, // 向左侧退出
        animationSpec = tween(durationMillis = anim.duration.toInt())
    ) + fadeOut(animationSpec = tween(anim.duration.toInt()))
}
fun slideInRight(context: Context): EnterTransition {
    val anim = AnimationUtils.loadAnimation(context, R.anim.slide_in_right)
    return slideInHorizontally(
        initialOffsetX = { it }, // 从左侧进入
        animationSpec = tween(durationMillis = anim.duration.toInt())
    )// + fadeIn(animationSpec = tween(anim.duration.toInt()))
}

fun slideOutRight(context: Context): ExitTransition {
    val anim = AnimationUtils.loadAnimation(context, R.anim.slide_out_right)
    return slideOutHorizontally(
        targetOffsetX = { it }, // 向左侧退出
        animationSpec = tween(durationMillis = anim.duration.toInt())
    ) //+ fadeOut(animationSpec = tween(anim.duration.toInt()))
}




@Composable
fun StatusBarBox(offsetTop: Int = 26, bgcolor:Color=colorScheme.primary){
    if(offsetTop > 0) {
        Box(
            modifier = Modifier.height(offsetTop.dp).fillMaxWidth().background(bgcolor),
        )
    }
}

@Composable
fun BottomBarBox(offsetBottom: Int = 16,color: Color = colorScheme.primaryContainer) {
    if(offsetBottom > 0) {
        Box(
            modifier = Modifier.height(offsetBottom.dp).fillMaxWidth().background(color),
        )
    }
}
@Composable
fun FhcTopAppBar(@StringRes title: Int,  actions: @Composable (RowScope.() -> Unit) = {}, navigationIcon: @Composable (() -> Unit)? = null, onTopAppBarPositioned: ((LayoutCoordinates) -> Unit)? = null) {
    FhcTopAppBar(stringResource(title), actions= actions, navigationIcon = navigationIcon, onTopAppBarPositioned = onTopAppBarPositioned)
}
@Composable
fun FhcTopAppBar(title: String,  actions: @Composable (RowScope.() -> Unit) = {}, navigationIcon: @Composable (() -> Unit)? = null, onTopAppBarPositioned: ((LayoutCoordinates) -> Unit)? = null) {
    val statusBarHeight = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()

    Column (modifier = Modifier.background(color = colorScheme.primary).onGloballyPositioned {
        if(onTopAppBarPositioned != null) onTopAppBarPositioned(it)
    },){
        StatusBarBox()
        TopAppBar(
            modifier = Modifier.fillMaxWidth(),
            title = { Text(text = title, style = androidx.compose.material3.MaterialTheme.typography.titleLarge, fontWeight = FontWeight.ExtraBold ) },
            navigationIcon = navigationIcon,
            backgroundColor = Color.Transparent,
            contentColor = colorScheme.onPrimary,
            actions =actions,
            elevation = 0.dp
        )
    }
}
